Глава 13

Массивы, структуры и списки CFML

Как было сказано в главе 9, ColdFusion доступно достаточно большое количество типов переменных. В той же главе мы постарались описать каждый из существующих типов, к которым относятся и такие типы, как массивы (arrays), структуры (structures) и списки (lists). На наш взгляд эти типы заслуживают отдельного внимания. При большом количестве отдельных переменных более эффективно использовать вместо них массивы, структуры или списки.

Массивы

Массивы (arrays) — это группа переменных одного типа, доступ к которым осуществляется с помощью общего имени. Хотя функция ArrayNew только поддерживает создание массивов до трехмерной размерности, массив не имеет предела на размер или максимальное значение.

Надо отметить, что массивы ColdFusion несколько отличаются от традиционных массивов, т. к. они являются динамическими, и если для обычных массивов их размер постоянен и симметричен, то массивы ColdFusion могут иметь ряды, отличающиеся друг от друга в зависимости от добавленных или удаленных данных.

Создание массива

Для использования массива необходимо предварительно его объявить:

<CFSET MyNewArray = ArrayNew(x)>

где х — число, отражающее размерность массива, которое может принимать значение от 1 до 3.

К примеру, создадим одномерный массив и запишем в уже существующий массив два элемента следующим образом:

<CFSET CruiseArray = ArrayNew(l)>

<CFSET CruiseArray[1] = "Museum of Jewish Horitage">

<CFSET CruiseArray[2] = "Ellis Island">

В следующем примере создадим двумерный массив и заполним его:

<CFSET TravelerArray = ArrayNew(2)>

<CFSET TravelerArray[1][1] = "Nomar">

<CFSET TravelerArray[1][2] = "Garciaparra">

<CFSET TravelerArray[2][1] = "Pedro">

<CFSET TravelerArray[2][2] = "Martinez">

Как уже было замечено, максимальное значение размерности массива в ColdFusion определяется значением 3 (трехмерный). Однако всегда можно создать массив массивов, т. е. когда массиву назначается вложенный элемент, являющийся также массивом. При этом за счет вложенного массива увеличивается и размерность внешнего массива. Например:

<CFSET TravelerArray = ArrayNew(2)>

<CFSET TicketArray = ArrayNew(3)>

<CFSET TicketArray[3][2] [1] = TravelerArrayX

<CFSET TicketArray[3][2][1][1][1] = "Buying">

Проверка массива

Добавление элементов

Например:

<HTML>

<HEAD>

<TITLE>myArray</TITLE>

</HEAD>

<BODY>

<CFSET CruiseArray = ArrayNew(l)>

<CFSET CruiseArray[1] =

"World Financial Center">

<CFSET CruiseArray[2] =

"Ellis Island">

<CFSET ArrayPrepend{CruiseArray,

"World Trade Center")>

<CFSET ArrayAppendtCruiseArray,

"Statue of Liberty")>

<CFSET ArraylnsertAt(CruiseArray,

3, "Battery Park")>

<CFSET ArraySet(CruiseArray, 6,

8, "Repair")>

<CFIF IsArray(CruiseArray)

AND ArraylsEmpty(CruiseArray) eq false>

<CFLOOP INDEX = "i" FROM = "1"

TO = #ArrayLen(CruiseArray)#>

<CFOUTPUT>#i#. #CruiseArray[i]#</CFOUTPUT><br>

</CFLOOP> </CFIF> </BODY> </HTML>

В результате приведенного выше примера создается одномерный массив CruiseArray с восемью элементами. При этом значения элементов массива выводятся на экран в следующем виде:

  1. World Trade Center
  2. World Financial Center
  3. Battery Park
  4. Ellis Island
  5. Statue of Liberty 6. Repair
  6. Repair 8. Repair

Также заполнение массива можно осуществлять непосредственно значениями из базы данных, используя для этой цели тег условного цикла <CFLOOP> с атрибутом QUERY, как показано ниже:

<HTML> <HEAD>

<TITLE>myArray2d</TITLE>

</HEAD> <BODY>

<CFQUERY NAME="GetTour" DATASOURCE="fapplication.dsn#">

SELECT Key_tou, Name_tou FROM Tour ORDER BY Key_tou </CFQUERY>

<CFSET TourArray2d = ArrayNew(2)>

<CFLOOP QUERY="GetTour">

<CFSET TourArray2d[CurrentRow][1] =

Key_tou[CurrentRow]>

<CFSET TourArray2d[CurrentRow][2] =

Name_tou[CurrentRow]> </CFLOOP>

<CFIF IsArray(TourArray2d) AND

ArraylsEmpty(TourArray2d) eq false>

<CFLOOP INDEX = "i" FROM = "1" TO =

lArrayLen(TourArray2d)#>

<CFOUTPUT>#TourArray2d[i][1]#

#TourArray2d[i][2]#</CFOUTPUT><br>

</CFLOOP> </CFIF> </BODY> </HTML>

В результате выполнения приведенного примера создается двумерный массив TourArray2d с присвоением его элементам значений в зависимости от содержимого базы данных и последующим выводом их на экран.

Регулирование положением элементов массива

Для функции ArraySort можно задавать следующие типы сортировки (sort_type):

Также функция ArraySort поддерживает сортировку (sort_order):

Например, для сортировки уже существующего массива CruiseArray в алфавитном порядке по возрастанию достаточно включить следующую строку кода:

<CFSET ArraySort(CruiseArray, "Text", "Asc")>

В результате элементы для нашего примера будут отсортированы следующим образом:

  1. Battery Park
  2. Ellis Island
  3. Repair
  4. Repair
  5. Repair
  6. Statue of Liberty
  7. World Financial Center
  8. World Trade Center

Например, чтобы переставить местами первый и шестой элементы в уже отсортированном массиве CruiseArray, достаточно включить следующую строку кода:

<CFSET ArraySwap(CruiseArray, 1, 6)>

В результате список элементов массива CruiseArray приобретет следующий вид:

  1. Statue of Liberty
  2. Ellis Island
  3. Repair
  4. Repair
  5. Repair
  6. Battery Park
  7. World Financial Center
  8. World Trade Center

Удаление элементов

Например, для очистки уже существующего массива CruiseArray достаточно включить следующую строку кода:

<CFSET ArrayClear(CruiseArray)>

Если есть необходимость удалить третий по счету элемент массива CruiseArray, следует включить строку кода, показанную ниже:

<CFSET ArrayDeleteAt(CruiseArray, 3)>

Обработка значений элементов

<HTML> <HEAD>

<TITLE>myArray</TITLE>

</HEAD> <BODY>

<CFQUERY NAME="GetTour" DATASOURCE="#application.dsn#">

SELECT CostAdult_tou

FROM Tour </CFQUERY>

<CFSET CostArray = ArrayNew(l)>

<CFLOOP QUERY="GetTour">

<CFSET CostArray[CurrentRow] = CostAdult_tou[CurrentRow]> </CFLOOP>

<CFIF IsArray(CostArray) AND ArraylsEmpty(CostArray) eq false>

<CFLOOP INDEX = "i" FROM = "1" TO = #ArrayLen(CostArray)#>

<CFOUTPUT>#CostArray[i]#</CFOUTPUT><br>

</CFLOOP> </CFIF> <br>

<CFOUTPUT>CostAvg: ttArrayAvg(CostArray)#</CFOUTPUT><br>

<CFOUTPUT>CostMax: #ArrayMax(CostArray)#</CFOUTPUT><br>

<CFOUTPUT>CostMin: #ArrayMin(CostArray)#</CFOUTPUT><br>

<CFOUTPUT>CostSum: #ArraySum(CostArray)#</CFOUTPUT><br>

</BODY> </HTML>

Результат работы приведенного выше кода таков:

13.00 20.00 24.00 20.00

CostAvg: 19.25

CostMax: 24

CostMin: 13

CostSum: 77

Преобразование массивов

Функция AfrayToList (array [, delimiter]} возвращает список элементов, преобразуя данные из массива. Здесь delimiter воспринимается как разделитель. По умолчанию разделителем является запятая (,).

Например, для создания списка, получаемого преобразованием данных уже существующего массива CostArray, достаточно включить следующий код:

<CFSET CostList = ArrayToList(CostArray)>

<CFOUTPUT>#CostList#</CFOUTPUT>

Результатом будет строка, отображающая содержание нового списка:

13.00,20.00,24.00,20.00 Или, к примеру:

<CFSET CostList2 = ArrayToList(CostArray, "---")>

<CFOUTPUT>#CostList2#</CFOUTPUT>

Здесь же результат несколько изменится и будет таким:

13 . 00—20. 00—24 . 00—20. 00

Размер массива

Функция ArrayResize (array, minimum_size) задает размер массива.

Например:

<CFSET ArrayResize(CruiseArray, 30)>

Таким образом, мы определяем минимальный размер массива, равный 30 элементам.

Структуры

Вы можете использовать структуры (structures), чтобы создавать и поддерживать пары ключевых значений, обращаться к связанным символьным значениям как к общности, а не как к индивидуальным значениям, или создавать ассоциативные массивы.

Создание структуры

Для использования структуры необходимо предварительно ее объявить:

<CFSET MyNewStruct = StructNew()>

К примеру, создадим структуру и присвоим значения двум ее элементам:

<CFSET TravelerStruct = StructNew()>

<CFSET TravelerStruct["RS1_98"] = "Nomar Garciaparra">

<CFSET TravelerStruct["RS2_98"] = "Pedro Martinez">

При этом был использован синтаксис ассоциативных массивов. Однако подобного результата можно добиться, применяя объектно-ориентированный синтаксис доступа к элементам, например:

<CFSET TravelerStruct = StructNew()>

<CFSET TravelerStruct.RS1_98 = "Nomar Garciaparra">

<CFSET TravelerStruct.RS2_98 = "Pedro Martinez">

Впрочем, в случае объектно-ориентированного синтаксиса необходимо, чтобы ключ, указанный после точки, начинался с буквы, и в названии ключа были использованы буквы, цифры и символы подчеркивания без разделительных пробелов. Приведем пример воспринимаемых и невоспринимаемых наименований ключей при использовании объектно-ориентированного синтаксиса.

Воспринимаемые наименования:

Невоспринимаемые наименования:

Также присвоение значений элементов структуры можно осуществлять с помощью функций.

Проверка структуры

Добавление элементов и модификация структуры

<HTML> <HEAD>

<TITLE>myStruct</TITLE>

</HEAD> <BODY>

<CFSET TravelerStruct = StructNew()>

<CFSET Structlnsert(TravelerStruct, "RS1_98","Nomar Garciaparra")>

<CFSET Structlnsert(TravelerStruct, "RS2_98","Pedro Martinez")>

<CFSET Structlnsert(TravelerStruct, "RS3_98","Tom Gordon")>

<CFSET Structlnsert(TravelerStruct, "RS4_98","Mike Stanley")>

<CFSET Structlnsert(TravelerStruct, "RS5_98","Reggie Jefferson")>

<CFSET Structlnsert(TravelerStruct, "RS6_98","Mark Portugal")>

<CFSET TravelerStruct2 = StructNew()>

<CFSET Structlnsert(TravelerStruct2, "RS7 98","John Valentin")>

<CFSET StructInsert (TravelerStruct2, "RS8_98", "Jose Offerman")>

<CFSET structlnsert(TravelerStruct2, "RS9_98","Jason Varitek")>

<CFSET StructUpdate(TravelerStruct2, "RS9_98","Trot Nixon")>

<CFSET StructAppend(TravelerStruct, TravelerStruct2)>

<CFIF IsStruct(TravelerStruct) AND StructIsEmpty(TravelerStruct)

eq false> <CFLOOP COLLECTION = #TravelerStruct# ITEM = "i">

<CFOUTPUT>#i# - #TravelerStruct[i]#</CFOUTPUTXbr> </CFLOOP> </CFIF> </BODY> </HTML>

В результате выполнения приведенного выше примера создается структура TravelerStruct с девятью значениями в соответствии с ключами. При этом значения структуры выводятся на экран в порядке добавления:

RS1_98 — Nomar Garciaparra RS2_98 - Pedro

Martinez RS3_98 - Tom Gordon RS4_98 - Mike

Stanley RS5_98 — Reggie Jefferson RS6_98 - Mark

Portugal RS7_98 - John Valentin RS8_98 - Jose

Offerman RS9_98 - Trot Nixon

Удаление элементов структуры

Например, для очистки уже существующей структуры TravelerStruct достаточно включить следующую строку кода:

<CFSET Structciear(TravelerStruct)>

Если есть необходимость удалить элемент структуры Travelerstruct со значением ключа RS7_98 и при этом убедиться, что попытка удаления оказалась удачной, необходимо включить код, показанный ниже:

<CFSET isDel = StructDelete(TravelerStruct, "RS7_98","Yes")>

<CFIF isDel eq true>

Item Delete </CFIF>

Или так:

<CFIF StructKeyExists(TravelerStruct, "RS7_98")>

<CFSET StructDelete(TravelerStruct, "RS7_98")>

</CFIF>

Преобразование структур

Например, для создания списка ключей, получаемого преобразованием данных уже существующей структуры TravelerStruct, достаточно включить следующий код:

<CFSET TravelerList = StructKeyList(TravelerStruct)>

<CFOOTPUT>#TravelerListtt</CFOUTPUT>

Результатом чего будет строка, отображающая содержание нового списка:

RS1_98,RS2_98,RS3_98,RS4_98,RS5_98,

RS6_98,RS7_98,RS8_98,RS9_98

Другие функции обработки структур

Например, следующая строка позволяет скопировать структуру TravelerStruct во вновь Созданную структуру TravCopyStruct: <CFSET TravCopyStruct = StructCopy(TravelerStruct)>

Например, для осуществления поиска значений по ключу RS4_98 в структуре TravelerStruct необходимо включить следующую пару строк кода:

<CFSET ResultFind = StructFind(TravelerStruct, "RS4_98")>

<CFOUTPUT>|ResultFind#</CFOUTPUT>

Результатом для нашего примера будет вывод найденного значения:

Mike Stanley

Списки

Списки (lists) — специальный символьный тип, составленный из элементов, отделенных разделителями.

Вы можете самостоятельно определять разделитель для списка. Причем разделитель может состоять из нескольких символов. По умолчанию в качестве разделителя принимается запятая (,).

Разделители перед первым элементом и после последнего элемента игнорируются.

Структура списков — плоская, т. е. списки не могут быть вложены друг в друга. Также, списки не могут содержать никакие "пустые" элементы. Однако список может быть пуст. При этом он эквивалентен пустому значению "".

В следующих разделах при описании функций обработки списков параметр delimiter необходимо воспринимать как разделитель.

Поиск, сортировка, проверка и просмотр списков

Для функции ListSort так же, как и для функции ArraySort, можно задавать следующие типы сортировки (sort_type):

Также функции Listsort поддерживает сортировку (sort_order):

<HTML> <HEAD>

<TITLE>myList</TITLE> </HEAD> <BODY>

<CFSET MyList = "Black,Magenta,Cyan,Orange,Darkgray,Pink,Gray,White, Lightgray,Yellow">

<CFOUTPUT>List: #MyListl</CFOUTPUTXbr>

<CFOUTPUT>Count of elements: #ListLen (MyList)

#</CFOUTPUT><br>

<CFOUTPUT>The first element: #ListFirst(MyList)

#</CFOUTPUT><br>

<CFOUTPUT>The last element: #ListLast(MyList)

#</CFOUTPUT><br>

<CFOUTPUT>The third element: #ListGetAt (MyList,

3) #</CFOUTPUT><br>

<CFOUTPUT>The element — "Orange" has number of a position:

#ListFind(MyList, "Orange") #</CFOUTPUT><br>

</BODY> </HTML>

В результате приведенного выше примера на экран будет выведено следующее:

List: Black,Magenta,Cyan,Orange,

Darkgray,Pink,Gray,White,Lightgray,

Yellow Count of elements: 10 The

first element: Black

The last element: Yellow

The third element: Cyan

The element — "Orange" has number of a position: 4

Изменение и преобразование списков

Например:

<HTML> <HEAD>

<TITLE>myList</TITLE> </HEAD> <BODY>

<CFSET MyList =

"Black,Magenta,Cyan,Orange,Darkgray,

Pink,Gray,White,Lightgray,Yellow">

<CFOUTPUT>List: #MyList#</CFOUTPUTXbr>

<CFSET myColorArray = ListToArray

(fListAppend(MyList, "NewColor")#)>

<CFLOOP INDEX = "i" FROM = "1" TO =

#ArrayLen(myColorArray)#>

<CFOUTPUT>#i#. #myColorArray[i]

#</CFOUTPUT><br> </CFLOOP>

</BODY> </HTML>

В результате приведенного выше примера на экран будет выведено следующее:

List: Black,Magenta,Cyan,Orange,Darkgray,

Pink,Gray,White,Lightgray,Yellow

1. Black

2. Magenta

3. Cyan

4. Orange

5. Darkgray

6. Pink

7. Gray

8. White

9. Lightgray

10. Yellow

11. NewColor

В предыдущих примерах, демонстрирующих обработку списков, мы определяли строковую переменную myList вручную. Впрочем, список также можно сформировать из предварительно выполненного запроса. К примеру, получим список круизов из уже знакомой нам базы данных cruise и отсортируем полученные значения по алфавиту, используя функцию ListSort:

<HTML> <HEAD>

<TITLE>myList</TITLE> </HEAD> <BODY>

<CFQUERY NAME="GetTour" DATASOURCE="#application.dsn#"> SELECT *

FROM Tour </CFQUERY>

<CFSET myListTour = ValueList(GetTour.Name_tou)> <CFOUTPUT>#ListSort(myListTour, "Text", "Asc")#

</CFOUTPUT> </BODY> </HTML>

В результате работы приведенного примера на экран будет выведен список маршрутов через запятую, как показано ниже:

1-hr Seaport Liberty,2-hr Harbor Lights Evening,2-hr Semi Circle,The Full Island

Резюме

В данной главе вы познакомились с возможностями обработки массивов, структур и списков. Эти типы данных облегчают понимание ColdFusion и в дальнейшем позволят вам с легкостью разрабатывать собственные Web-приложения.